package com.aplink.generic;

import java.util.ArrayList;

import android.app.ActionBar;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.widget.SearchView;
import android.widget.SearchView.OnCloseListener;

import com.aplink.generic.adapter.ActionbarSelectionAdapter;
import com.aplink.generic.bitmap.ImageCache;
import com.aplink.generic.bitmap.ImageFetcher;
import com.aplink.generic.constant.BundleConstant;
import com.aplink.generic.constant.type.ActionType;
import com.aplink.generic.constant.type.ControlType;
import com.aplink.generic.constant.type.DialogStatus;
import com.aplink.generic.controller.GenericApplication;
import com.aplink.generic.database.DatabaseHelper;
import com.aplink.generic.database.SqlMethods;
import com.aplink.generic.dialog.ApLinkProgressDialog;
import com.aplink.generic.dialog.SparseDialog;
import com.aplink.generic.dictionary.GenericDictionary;
import com.aplink.generic.handler.DataHandler;
import com.aplink.generic.handler.EventHandler;
import com.aplink.generic.handler.GenericHandler;
import com.aplink.generic.handler.WebserviceHandler;
import com.aplink.generic.interfaces.DatabaseDelete;
import com.aplink.generic.interfaces.DatabaseGet;
import com.aplink.generic.interfaces.DatabaseInsert;
import com.aplink.generic.interfaces.DatabaseUpdate;
import com.aplink.generic.interfaces.FinishActivityListener;
import com.aplink.generic.interfaces.OnActionBarSelectionListener;
import com.aplink.generic.interfaces.OnActivityResultListener;
import com.aplink.generic.interfaces.OnBackPressedListerner;
import com.aplink.generic.interfaces.OnSearchListener;
import com.aplink.generic.interfaces.StartActivityListener;
import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.GenericAttribute;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.pojo.controlspec.ButtonSpec;
import com.aplink.generic.pojo.controlspec.ControlSpec;
import com.aplink.generic.pojo.controlspec.GallerySpec;
import com.aplink.generic.pojo.controlspec.actionbar.ActionBarSpec;
import com.aplink.generic.pojo.controlspec.actionbar.SearchViewSpec;
import com.aplink.generic.pojo.controlspec.actionbar.SelectionSpec;
import com.aplink.generic.pojo.controlspec.menu.MenuItemSpec;
import com.aplink.generic.pojo.formdesign.Column;
import com.aplink.generic.pojo.formdesign.FormDesign;
import com.aplink.generic.pojo.formdesign.InitValue;
import com.aplink.generic.pojo.formdesign.PassingValue;
import com.aplink.generic.pojo.formdesign.SelectWhere;
import com.aplink.generic.sharepreference.GenericSharePreference;
import com.aplink.generic.util.Language;
import com.aplink.generic.util.LogUtil;
import com.aplink.generic.util.ResourcesHelper;
import com.aplink.generic.util.objectrule.EnableCondition;
import com.aplink.generic.util.objectrule.Target;
import com.aplink.generic.util.objectrule.TargetCollection;
import com.aplink.generic.util.validation.ControlValidation;
import com.aplink.generic.util.validation.ControlValidationTask;
import com.aplink.generic.util.validation.ValidationResult;
import com.aplink.generic.widgets.ApLinkBarcodeScanner;
import com.aplink.generic.widgets.ApLinkBaseView;
import com.aplink.generic.widgets.ApLinkButton;
import com.aplink.generic.widgets.ApLinkCheckBox;
import com.aplink.generic.widgets.ApLinkDateTimePicker;
import com.aplink.generic.widgets.ApLinkEditText;
import com.aplink.generic.widgets.ApLinkGallery;
import com.aplink.generic.widgets.ApLinkGoogleMaps;
import com.aplink.generic.widgets.ApLinkGridView;
import com.aplink.generic.widgets.ApLinkImageView;
import com.aplink.generic.widgets.ApLinkListView;
import com.aplink.generic.widgets.ApLinkPopupMenu;
import com.aplink.generic.widgets.ApLinkRadioButton;
import com.aplink.generic.widgets.ApLinkSpinner;
import com.aplink.generic.widgets.ApLinkSwitch;
import com.aplink.generic.widgets.ApLinkTabhost;
import com.aplink.generic.widgets.ApLinkTextview;
import com.aplink.generic.widgets.ApLinkViewPager;
import com.aplink.generic.xmlparser.ContentDataParser;
import com.aplink.generic.xmlparser.FormDesignParser;

public class GenericFragment extends Fragment implements OnClickListener,
        ActionBar.OnNavigationListener, OnBackPressedListerner,
        AnimationListener {
    public static final String CONTENT_DATA = "CONTENT_DATA";
    public static final String FORM_DESIGN = "FORM_DESIGN";
    private static final String IMAGE_CACHE_DIR = "images";
    public static final int NONE = 0;

    public static final GenericFragment newInstance(final int formDesignID,
            final int contentDataID) {
        final GenericFragment fragment = new GenericFragment();
        final Bundle bundle = new Bundle();
        bundle.putInt(GenericFragment.FORM_DESIGN, formDesignID);
        bundle.putInt(GenericFragment.CONTENT_DATA, contentDataID);
        fragment.setArguments(bundle);
        return fragment;
    }

    private boolean isAlowRefresh;
    private ActionbarSelectionAdapter mActionbarSelectionAdapter;
    private OnActionBarSelectionListener mActionBarSelectionListener;
    private OnActivityResultListener mActivityResultHandler;
    private SparseDialog mApLinkAlertDialog;
    private ApLinkProgressDialog mApLinkProgressDialog;
    private GenericDictionary<String, ApLinkBaseView> mBaseViewByID;
    private GenericDictionary<String, ApLinkBaseView> mBaseViewByMappingName;
    private ContentData mContentData;
    private EventHandler mControlEventHandler;
    private DataHandler mDatabaseHandler;
    private FormDesign mFormDesign;
    private GenericHandler mGenericHandler;
    private GenericDictionary<String, String> mHashPassedValues;
    private int mIgnoreSelectionIndex;
    private ImageFetcher mImageFetcher;
    private GenericObject mInitValues;
    private ArrayList<ApLinkBaseView> mListRefreshView;
    private OnSearchListener mOnSearchListener;
    private GenericObject mPassedGenericObject;
    private PassingValue mPassingValue;
    private SearchViewSpec mSearchViewSpec;
    private ControlSpec mSelectedControlSpec;
    private GenericObject mSelectedObject = null;
    private SqlMethods mSqlMethods = null;
    private Target mTargetClass = null;
    private GenericDictionary<String, ArrayList<ControlSpec>> mValidationGroups;
    private ArrayList<ApLinkBaseView> mValueListViews;

    private View mView;

    private WebserviceHandler mWebserviceHandler;

    private OnClickListener onActionbarButtonClickListener = new OnClickListener() {

        @Override
        public void onClick(final View v) {
            onSubmit((MenuItemSpec) v.getTag());
        }
    };

    public GenericFragment() {
    }

    public void clearAll() {
        initData();
        loadDataToForm();
    }

    public View findViewByID(final String id) {
        final int viewID = ResourcesHelper.getViewIdByName(id);
        if (viewID != ResourcesHelper.RESOURCE_NOT_FOUND) {
            return getView().findViewById(viewID);
        }
        return null;
    }

    public FinishActivityListener finish() {
        return new FinishActivityListener() {

            @Override
            public void finishActivity() {
                GenericFragment.this.getActivity().finish();
                GenericFragment.this.getActivity()
                        .overridePendingTransition(
                                GenericFragment.this.getFormDesign()
                                        .getAnimationInID(),
                                GenericFragment.this.getFormDesign()
                                        .getAnimationOutID());
            }
        };
    }

    public void finishActivity() {
        finish().finishActivity();
    }

    public OnActionBarSelectionListener getActionBarSelectionListener() {
        return this.mActionBarSelectionListener;
    }

    public OnActivityResultListener getActivityResultListener() {
        return this.mActivityResultHandler;
    }

    public SparseDialog getAlertDialog() {
        return this.mApLinkAlertDialog;
    }

    public ApLinkProgressDialog getApLinkProgressDialog() {
        return this.mApLinkProgressDialog;
    }

    public ApLinkBaseView getAPLinkViewByID(final String id) {
        return this.mBaseViewByID.get(id);
    }

    public Context getApplicationContext() {
        return getActivity().getBaseContext();
    }

    public GenericObject getBindingObject() {
        handleInitValue();
        return this.getBindingObject(false);
    }

    public GenericObject getBindingObject(final boolean isForceRenewCreatedTime) {
        final GenericObject objValues = new GenericObject();
        final String createdTime = GenericApplication.getInstance()
                .getCreatedTime();
        final ContentData objPropCol = getContentData();
        objValues.setTableName(objPropCol.getMainTable());
        for (int i = 0; i < objPropCol.size(); i++) {
            final ObjPropInfo propInfo = objPropCol.valueAt(i);
            final ApLinkBaseView baseView = this.mBaseViewByMappingName
                    .get(propInfo.getColumnName());
            GenericAttribute attribute = null;
            if (baseView != null) {
                attribute = baseView.getAttribute();
            } else {
                GenericAttribute passedAttribute = null;
                if (GenericObject.isContainValueOf(this.mInitValues, propInfo)) {
                    passedAttribute = this.mInitValues.get(propInfo
                            .getFullColumnName());
                } else if (GenericObject.isContainValueOf(
                        this.mPassedGenericObject, propInfo)) {
                    if (propInfo.isCreatedTime()) {
                        if (!isForceRenewCreatedTime) {
                            passedAttribute = this.mPassedGenericObject
                                    .get(propInfo.getFullColumnName());
                        }
                    } else {
                        passedAttribute = this.mPassedGenericObject
                                .get(propInfo.getFullColumnName());
                    }
                }

                if ((passedAttribute != null) && passedAttribute.isValid()) {
                    attribute = passedAttribute;
                } else if (propInfo.isCreatedTime()
                        || (propInfo.isKey() & !propInfo.isAuto())) {
                    attribute = GenericAttribute.obtain(createdTime, propInfo);
                } else {
                    attribute = GenericAttribute.obtain(null, propInfo);
                }
            }
            objValues.put(propInfo.getFullColumnName(), attribute);
        }
        for (final ApLinkBaseView baseView : this.mValueListViews) {
            objValues.merge(baseView.getListAttributes());
        }
        return objValues;
    }

    public String getClassName() {
        return ((Object) this).getClass().getSimpleName();
    }

    public final ContentData getContentData() {
        return mContentData;
    }

    public DatabaseDelete getDatabaseDelete() {
        return DatabaseHelper.getInstance();
    }

    public DatabaseGet getDatabaseGet() {
        return DatabaseHelper.getInstance();
    }

    public DataHandler getDatabaseHandler() {
        return this.mDatabaseHandler;
    }

    public DatabaseInsert getDatabaseInsert() {
        return DatabaseHelper.getInstance();
    }

    public DatabaseUpdate getDatabaseUpdate() {
        return DatabaseHelper.getInstance();
    }

    public EventHandler getEventHandler() {
        return this.mControlEventHandler;
    }

    public final FormDesign getFormDesign() {
        return mFormDesign;
    }

    public String getFullClassName() {
        return ((Object) this).getClass().getName();
    }

    public GenericHandler getGenericHandler() {
        if (this.mGenericHandler == null) {
            this.mGenericHandler = new GenericHandler(this);
        }
        return this.mGenericHandler;
    }

    public GenericDictionary<String, String> getHashPassedValues() {
        return this.mHashPassedValues;
    }

    public ImageFetcher getImageFetcher() {
        return this.mImageFetcher;
    }

    public GenericObject getInitValues() {
        return this.mInitValues;
    }

    public OnClickListener getOnActionbarButtonClickListener() {
        return this.onActionbarButtonClickListener;
    }

    public OnSearchListener getOnSearchListener() {
        return this.mOnSearchListener;
    }

    public GenericObject getPassedGenericObject() {
        return this.mPassedGenericObject;
    }

    public ProgressDialog getProgressDialog(final ActionType actionType) {
        if (this.mApLinkProgressDialog != null) {
            return this.mApLinkProgressDialog.getProgressDialog(actionType
                    .getValue());
        }
        return null;
    }

    private SearchViewSpec getSearchView() {
        if (mSearchViewSpec == null) {
            mSearchViewSpec = getFormDesign().getActionBar()
                    .getSearchViewSpec();
        }
        return mSearchViewSpec;
    }

    public GenericObject getSelectedObject() {
        return this.mSelectedObject;
    }

    public SqlMethods getSqlMethods() {
        return this.mSqlMethods;
    }

    public SqlMethods getSqlMethods(final GenericObject object,
            final ArrayList<Column> conditions) {
        if (this.mFormDesign != null) {
            final SqlMethods sqlMethods = SqlMethods.getInstance();
            for (int i = 0; i < conditions.size(); i++) {
                final Column column = conditions.get(i);
                final String cond = column.getColumnName();
                if (column.getDefaultValue() != null) {
                    final String value = column.getDefaultValue();
                    sqlMethods.equal(cond, value);
                    if (i < (conditions.size() - 1)) {
                        sqlMethods.and();
                    }
                } else {
                    final GenericAttribute obj = object.get(cond);
                    if ((obj != null) && !TextUtils.isEmpty(obj.getValue())) {
                        final ObjPropInfo objPropInfo = getContentData().get(
                                cond);
                        final String value = String.valueOf(obj.getValue());
                        sqlMethods.equal(objPropInfo, value);
                        if (i < (conditions.size() - 1)) {
                            sqlMethods.and();
                        }
                    }
                }
            }
            return sqlMethods;
        }
        return null;
    }

    protected SqlMethods getSqlMethods(final GenericObject object,
            final String[] conditions) {
        if (this.mFormDesign != null) {
            final SqlMethods sqlMethods = SqlMethods.getInstance();
            for (int i = 0; i < conditions.length; i++) {
                final String cond = conditions[i];
                final GenericAttribute obj = object.get(cond);
                final ObjPropInfo objPropInfo = getContentData().get(cond);
                final String value = String.valueOf(obj.getValue());
                sqlMethods.equal(objPropInfo, value);
                if (i < (conditions.length - 1)) {
                    sqlMethods.and();
                }
            }
            return sqlMethods;
        }
        return null;
    }

    public Target getTargetClass() {
        return this.mTargetClass;
    }

    public GenericDictionary<String, ArrayList<ControlSpec>> getValidationGroups() {
        return this.mValidationGroups;
    }

    public ApLinkBaseView getViewByMappingName(final String mappingName) {
        return this.mBaseViewByMappingName.get(mappingName);
    }

    public GenericDictionary<String, ApLinkBaseView> getViewsInLayout() {
        return this.mBaseViewByMappingName;
    }

    public WebserviceHandler getWebserviceHandler() {
        return this.mWebserviceHandler;
    }

    private void handleActionBarSelection() {
        final ActionBar actionBar = getActivity().getActionBar();
        SelectionSpec selectionSpec = null;
        if (getFormDesign().getActionBar() != null) {
            selectionSpec = getFormDesign().getActionBar().getSelectionSpec();
        }
        if (actionBar != null) {
            final ActionBarSpec actionBarSpec = getFormDesign().getActionBar();
            if (actionBarSpec != null) {
                actionBar.setDisplayHomeAsUpEnabled(actionBarSpec
                        .isDisplayHomeAsUp());
                actionBar.setDisplayShowHomeEnabled(actionBarSpec
                        .isDisplayShowHomeEnabled());
                if (!actionBarSpec.getButtons().isEmpty()) {
                    actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
                    actionBar.setCustomView(actionBarSpec
                            .getActionBarButton(this));
                    actionBar.setDisplayShowCustomEnabled(true);
                } else {
                    if (selectionSpec == null) {
                        actionBar.setDisplayShowTitleEnabled(true);
                        actionBar.setDisplayUseLogoEnabled(true);
                        actionBar.setDisplayShowHomeEnabled(true);
                        actionBar
                                .setNavigationMode(ActionBar.DISPLAY_SHOW_TITLE);
                        if (!TextUtils.isEmpty(actionBarSpec.getTitle())) {
                            actionBar.setTitle(actionBarSpec.getTitle());
                        }
                        if (!TextUtils.isEmpty(actionBarSpec.getSubTitle())) {
                            actionBar.setSubtitle(actionBarSpec.getSubTitle());
                        }
                        if (actionBarSpec.getIconID() != ResourcesHelper.RESOURCE_NOT_FOUND) {
                            actionBar.setIcon(actionBarSpec.getIconID());
                        }
                        if (GenericApplication.getInstance().getMainMenu() != null) {
                            actionBar.setDisplayHomeAsUpEnabled(true);
                            actionBar.setHomeButtonEnabled(true);
                        }
                    } else {
                        this.mIgnoreSelectionIndex = selectionSpec
                                .getIgnoreIndex();
                        actionBar.setDisplayShowTitleEnabled(false);
                        actionBar.setDisplayUseLogoEnabled(false);
                        actionBar.setDisplayShowHomeEnabled(false);
                        actionBar
                                .setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
                        this.mActionbarSelectionAdapter = new ActionbarSelectionAdapter(
                                getApplicationContext(), selectionSpec);
                        actionBar.setListNavigationCallbacks(
                                this.mActionbarSelectionAdapter, this);
                    }
                }
            }
        }
    }

    private void handleInitValue() {
        if (!this.mFormDesign.isEmpty()) {
            final InitValue initValue = this.mFormDesign.getInitValue();
            if (!initValue.isEmpty()) {
                final Intent intent = getActivity().getIntent();
                final Bundle bundle = intent.getExtras();
                final GenericObject passedValues = new GenericObject();
                if ((bundle != null)
                        && bundle.containsKey(BundleConstant.SELECTED_OBJECT)) {
                    final SparseArray<GenericAttribute> sparseArray = bundle
                            .getSparseParcelableArray(BundleConstant.SELECTED_OBJECT);

                    for (int i = 0; i < sparseArray.size(); i++) {
                        passedValues.put(sparseArray.keyAt(i),
                                sparseArray.valueAt(i));
                    }
                }
                this.mInitValues = new GenericObject();
                for (final Column column : initValue) {
                    final ObjPropInfo objPropInfo = getContentData().get(
                            column.getRealColumnName());
                    if (column.getPreferenceType() != null) {
                        final String value = GenericSharePreference
                                .getInstance().getValue(
                                        column.getPreferenceType());
                        final GenericAttribute attribute = GenericAttribute
                                .obtain(value, objPropInfo);
                        this.mInitValues.put(column.getRealColumnName(),
                                attribute);
                    } else if (column.getDefaultValue() != null) {
                        this.mInitValues.put(column.getRealColumnName(),
                                column.getDefaultValue());
                    } else if (passedValues != null) {
                        this.mInitValues.put(column.getRealColumnName(),
                                passedValues.get(column.getColumnName()));
                    }
                }
            }
        }
    }

    private void handlePassedObject() {
        final Intent intent = getActivity().getIntent();
        final Bundle bundle = intent.getExtras();
        if (!this.mFormDesign.isEmpty()) {
            final SelectWhere selectWhere = this.mFormDesign.getSelectWhere();
            if (!selectWhere.isEmpty()) {
                final GenericObject passedValues = new GenericObject();
                if ((bundle != null)
                        && bundle.containsKey(BundleConstant.SELECTED_OBJECT)) {
                    final SparseArray<GenericAttribute> sparseArray = bundle
                            .getSparseParcelableArray(BundleConstant.SELECTED_OBJECT);

                    for (int i = 0; i < sparseArray.size(); i++) {
                        passedValues.put(sparseArray.keyAt(i),
                                sparseArray.valueAt(i));
                    }
                }
                final GenericObject passedObjects = new GenericObject();
                for (final Column column : selectWhere) {
                    String value = null;
                    if (passedValues.containsKey(column.getColumnName())) {
                        value = passedValues.get(column.getColumnName())
                                .getValue();
                    }
                    if (TextUtils.isEmpty(value)) {
                        value = column.getDefaultValue();
                    }
                    if (!TextUtils.isEmpty(value)) {
                        passedObjects.put(column.getRealColumnName(), value);
                    }
                }
                if (this.mContentData == null) {
                    setPassedGenericObject(passedObjects);
                } else {
                    final SqlMethods sqlMethods = this.getSqlMethods(
                            new GenericObject(passedObjects), selectWhere);
                    this.mSqlMethods = sqlMethods;
                    if (!TextUtils.isEmpty(sqlMethods.toString())) {
                        final GenericObject genericObject = getDatabaseGet()
                                .get(getContentData(), sqlMethods.toString());
                        if (genericObject == null) {
                            setPassedGenericObject(new GenericObject(
                                    passedObjects));
                        } else {
                            try {
                                if (selectWhere.getTargetClass() == null) {
                                    setPassedGenericObject(genericObject);
                                } else {
                                    this.startActivity(
                                            selectWhere.getTargetClass(),
                                            selectWhere.getPassingValue());
                                    finishActivity();
                                }
                            } catch (final NameNotFoundException e) {
                                e.printStackTrace();
                            } catch (final ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            } else if (this.mFormDesign.isAlwayLoadFirstRecord()) {
                final GenericObject genericObject = getDatabaseGet().get(
                        getContentData(), null);
                setPassedGenericObject(genericObject);
            }
        }
    }

    public void handleValidationResult(final ControlSpec controlSpec,
            final ValidationResult result) {
        TargetCollection targetCollection = null;
        if (controlSpec instanceof MenuItemSpec) {
            targetCollection = ((MenuItemSpec) controlSpec)
                    .getTargetCollection();
        } else if (controlSpec instanceof ButtonSpec) {
            targetCollection = ((ButtonSpec) controlSpec).getTargetCollection();
        }
        final ActionType actionType = controlSpec.getActionType();
        if (result.isValid()) {
            mSelectedObject = this.getBindingObject();
            boolean isPassed = false;
            if (controlSpec instanceof MenuItemSpec) {
                isPassed = true;
            } else {
                isPassed = false;
                final EnableCondition enableCondition = controlSpec
                        .getEnableCondition();
                if (enableCondition == null) {
                    isPassed = true;
                } else {
                    if (enableCondition.isValid(this.mSelectedObject)) {
                        isPassed = true;
                    } else {
                        isPassed = false;
                        getAlertDialog().show(actionType,
                                DialogStatus.ENABLE_CONDITON_FAILED);
                    }
                }
            }
            if (isPassed) {
                if (targetCollection != null) {
                    try {
                        setTargetClass(targetCollection
                                .getTargetClass(this.mSelectedObject));
                    } catch (final NameNotFoundException
                            | ClassNotFoundException e) {
                        LogUtil.error(e.getMessage(), "onClick", getClassName());
                    }
                }
                if (actionType != null) {
                    getEventHandler().sendEmptyMessage(actionType.getCode());
                }
            }
        } else {
            if (actionType != null) {
                if (hasRegisterProgressDialog(actionType)) {
                    getProgressDialog(actionType).dismiss();
                }
                showInvalidValidationDialog(actionType, result);
            }
        }
    }

    public boolean hasActionBarSelectionFor(final String controlID) {
        if (getFormDesign().getActionBar() != null) {
            final SelectionSpec selectionSpec = getFormDesign().getActionBar()
                    .getSelectionSpec();
            if (selectionSpec != null) {
                return selectionSpec.getSearchFor().equalsIgnoreCase(controlID);
            }
        }
        return false;
    }

    public boolean hasRegisterAlertDialog(final ActionType actionType,
            final DialogStatus dialogStatus) {
        return getAlertDialog().has(actionType, dialogStatus);
    }

    public boolean hasRegisterProgressDialog(final ActionType actionType) {
        if (this.mApLinkProgressDialog != null) {
            return this.mApLinkProgressDialog.has(actionType);
        }
        return false;
    }

    protected void initData() {
        if ((this.mPassedGenericObject == null)
                || this.mPassedGenericObject.isEmpty()) {
            handlePassedObject();
        }
        handleInitValue();
        this.mHashPassedValues = new GenericDictionary<String, String>();
        if (this.mPassedGenericObject != null) {
            for (int i = 0; i < this.mPassedGenericObject.size(); i++) {
                final int key = this.mPassedGenericObject.keyAt(i);
                final GenericAttribute attribute = this.mPassedGenericObject
                        .get(key);
                String value = null;
                if (attribute.getValue() != null) {
                    value = attribute.getValue().toString();
                    if (TextUtils.isEmpty(value)) {
                        value = null;
                    }
                }
                if (attribute.getValue() != null) {
                    this.mHashPassedValues.put(key, value);
                } else {
                    this.mHashPassedValues.put(key, null);
                }
            }
        }
    }

    public void invalidateOptionsMenu() {
        if (getActivity() != null) {
            getActivity().invalidateOptionsMenu();
        }
    }

    public boolean isAlowRefresh() {
        return this.isAlowRefresh;
    }

    public ValidationResult isFormValidate(final ControlSpec controlSpec) {
        final String validationGroup = controlSpec.getValidationGroup();
        if (validationGroup != null) {
            return ControlValidation.getInstance().isFormValidate(this,
                    validationGroup);
        }
        final ValidationResult result = new ValidationResult();
        result.setValid(true);
        return result;
    }

    protected void loadDataToForm() {
        for (int i = 0; i < getFormDesign().size(); i++) {
            final ControlSpec controlSpec = getFormDesign().valueAt(i);
            final ControlType controlType = controlSpec.getControlType();
            int controlId = ResourcesHelper.RESOURCE_NOT_FOUND;
            if (controlType.equals(ControlType.TABHOST)) {
                controlId = android.R.id.tabhost;
            } else {
                controlId = ResourcesHelper.getViewIdByName(controlSpec
                        .getIDName());
            }
            if ((controlId == ResourcesHelper.RESOURCE_NOT_FOUND)
                    && (!controlType.equals(ControlType.DATETIME_PICKER))
                    && (!controlType.equals(ControlType.GOOGLE_MAPS))) {
                continue;
            }
            final View view = this.mView.findViewById(controlId);
            ApLinkBaseView baseView = null;
            if (controlType.equals(ControlType.BARCODE_SCANNER)) {
                baseView = new ApLinkBarcodeScanner(this, controlSpec, view);
            } else if (controlType.equals(ControlType.POPUP_MENU)) {
                baseView = new ApLinkPopupMenu(this, controlSpec, view);
            } else if (controlType.equals(ControlType.DATETIME_PICKER)) {
                baseView = new ApLinkDateTimePicker(this, controlSpec, view);
            } else if (controlType.equals(ControlType.BUTTON)) {
                baseView = new ApLinkButton(this, controlSpec, view);
            } else if (controlType.equals(ControlType.TEXTVIEW)) {
                baseView = new ApLinkTextview(this, controlSpec, view);
            } else if (controlType.equals(ControlType.LISTVIEW)) {
                baseView = new ApLinkListView(this, controlSpec, view);
                if (getSearchView() != null) {
                    if (getSearchView().getSearchFor().equalsIgnoreCase(
                            controlSpec.getIDName())) {
                        final OnSearchListener onSearchListener = ((ApLinkListView) baseView)
                                .getOnSearchListener();
                        setOnSearchListener(onSearchListener);
                    }
                }
            } else if (controlType.equals(ControlType.GRIDVIEW)) {
                baseView = new ApLinkGridView(this, controlSpec, view);
            } else if (controlType.equals(ControlType.EDITTEXT)) {
                baseView = new ApLinkEditText(this, controlSpec, view);
            } else if (controlType.equals(ControlType.SPINNER)) {
                baseView = new ApLinkSpinner(this, controlSpec, view);
            } else if (controlType.equals(ControlType.VIEWPAGER)) {
                baseView = new ApLinkViewPager(this, controlSpec, view);
            } else if (controlType.equals(ControlType.TABHOST)) {
                baseView = new ApLinkTabhost(this, controlSpec, view);
            } else if (controlType.equals(ControlType.IMAGEVIEW)) {
                baseView = new ApLinkImageView(this, controlSpec, view);
            } else if (controlType.equals(ControlType.RADIO_BUTTON)) {
                baseView = new ApLinkRadioButton(this, controlSpec, view);
            } else if (controlType.equals(ControlType.CHECKBOX)) {
                baseView = new ApLinkCheckBox(this, controlSpec, view);
            } else if (controlType.equals(ControlType.GALLERY)) {
                baseView = new ApLinkGallery(this, controlSpec, view);
                final GallerySpec gallerySpec = (GallerySpec) controlSpec;
                if ((gallerySpec.getImageWidth() + gallerySpec.getImageHeight()) == 0) {
                    final DisplayMetrics displayMetrics = getApplicationContext()
                            .getResources().getDisplayMetrics();
                    final int height = displayMetrics.heightPixels;
                    final int width = displayMetrics.widthPixels;
                    final int longest = (height > width ? height : width) / 2;
                    this.mImageFetcher = new ImageFetcher(
                            getApplicationContext(), longest);
                } else {
                    this.mImageFetcher = new ImageFetcher(
                            getApplicationContext(),
                            gallerySpec.getImageWidth(),
                            gallerySpec.getImageHeight());
                }
                final ImageCache.ImageCacheParams cacheParams = new ImageCache.ImageCacheParams(
                        getApplicationContext(),
                        GenericFragment.IMAGE_CACHE_DIR);
                cacheParams.setMemCacheSizePercent(0.25f);
                this.mImageFetcher.addImageCache(getFragmentManager(),
                        cacheParams);
                this.mImageFetcher.setImageFadeIn(true);
            } else if (controlType.equals(ControlType.SWITCH)) {
                baseView = new ApLinkSwitch(this, controlSpec, view);
            } else if (controlType.equals(ControlType.GOOGLE_MAPS)) {
                baseView = new ApLinkGoogleMaps(this, controlSpec, view);
            }
            if (baseView != null) {
                if (controlSpec.getMappingName() != null) {
                    this.mBaseViewByMappingName.put(
                            controlSpec.getMappingName(), baseView);
                }
                this.mBaseViewByID.put(controlSpec.getIDName(), baseView);
                if (controlSpec.isAutoRefreshValue()) {
                    this.mListRefreshView.add(baseView);
                }

                if (baseView.hasValueList()) {
                    this.mValueListViews.add(baseView);
                }

                if (controlSpec.getValidationGroup() != null) {
                    final String validationGroup = controlSpec
                            .getValidationGroup();
                    if (this.mValidationGroups.containsKey(validationGroup)) {
                        this.mValidationGroups.get(
                                controlSpec.getValidationGroup()).add(
                                controlSpec);
                    } else {
                        final ArrayList<ControlSpec> arrayList = new ArrayList<ControlSpec>();
                        arrayList.add(controlSpec);
                        this.mValidationGroups.put(validationGroup, arrayList);
                    }
                }
                baseView.initView();
            }
        }
    }

    public void nextPage() {
        if (this.mTargetClass != null) {
            try {
                this.startActivity(this.mTargetClass.getTargetClass(),
                        this.mTargetClass.getPassingValue());
            } catch (NameNotFoundException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    public void notifyDataSetChanged() {
        if (this.isAlowRefresh) {
            for (final ApLinkBaseView baseView : this.mListRefreshView) {
                baseView.notifyDataSetChanged();
            }
            this.isAlowRefresh = false;
        }
    }

    @Override
    public final void onActivityCreated(final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        onPrepareFragment();
        initData();
        loadDataToForm();
        onFragmentCreated();
    }

    @Override
    public void onActivityResult(final int requestCode, final int resultCode,
            final Intent data) {
        if (this.mActivityResultHandler != null) {
            this.mActivityResultHandler.onActivityResult(requestCode,
                    resultCode, data);
        }
    }

    @Override
    public void onAnimationEnd(final Animation animation) {
        onSubmit(this.mSelectedControlSpec);
    }

    @Override
    public void onAnimationRepeat(final Animation animation) {

    }

    @Override
    public void onAnimationStart(final Animation animation) {

    }

    @Override
    public void onBackPressed() {
        finishActivity();
    }

    @Override
    public void onClick(final View v) {
        onSubmit((ControlSpec) v.getTag());
    }

    @Override
    public void onCreate(final Bundle arg) {
        super.onCreate(arg);
        Language.updateLanguageSystem(getActivity().getBaseContext());
        final Bundle arguments = getArguments();
        mFormDesign = FormDesignParser.getInstance().parse(
                arguments.getInt(GenericFragment.FORM_DESIGN));
        mContentData = ContentDataParser.getInstance().parseIntoObjProp(
                arguments.getInt(GenericFragment.CONTENT_DATA));
        this.mFormDesign = getFormDesign();
        this.mGenericHandler = new GenericHandler(this);
        this.mControlEventHandler = new EventHandler(this);
        this.mWebserviceHandler = new WebserviceHandler(this);
        this.mDatabaseHandler = new DataHandler(this);
        this.mBaseViewByMappingName = new GenericDictionary<String, ApLinkBaseView>();
        this.mBaseViewByID = new GenericDictionary<String, ApLinkBaseView>();
        this.mListRefreshView = new ArrayList<ApLinkBaseView>();
        this.mValueListViews = new ArrayList<ApLinkBaseView>();
        this.mValidationGroups = new GenericDictionary<String, ArrayList<ControlSpec>>();
        this.mApLinkProgressDialog = getFormDesign().getApLinkProgressDialog();
        if (this.mApLinkProgressDialog != null) {
            this.mApLinkProgressDialog.init(this);
        }
        this.mApLinkAlertDialog = getFormDesign().getAlertDialog();
        if (this.mApLinkAlertDialog != null) {
            this.mApLinkAlertDialog.init(this);
        }
        setHasOptionsMenu(getFormDesign().hasOptionMenu());
    }

    @Override
    public View onCreateView(final LayoutInflater inflater,
            final ViewGroup container, final Bundle savedInstanceState) {
        final int layoutID = getFormDesign().getLayoutID();
        if (layoutID != ResourcesHelper.RESOURCE_NOT_FOUND) {
            this.mView = inflater.inflate(layoutID, container, false);
        }
        return this.mView;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        DatabaseHelper.getInstance().releaseDatabase();
        if (this.mImageFetcher != null) {
            this.mImageFetcher.setExitTasksEarly(true);
            this.mImageFetcher.flushCache();
            this.mImageFetcher.clearCache();
        }
    }

    protected void onFragmentCreated() {

    }

    public boolean onHandlePopupMenuItem(final MenuItemSpec menuItemSpec)
            throws NameNotFoundException, ClassNotFoundException {
        if ((menuItemSpec != null) && (menuItemSpec.getActionType() != null)) {
            this.mSelectedObject = menuItemSpec.getGenericObject();
            if (menuItemSpec.getTargetCollection() != null) {
                this.mTargetClass = menuItemSpec.getTargetCollection()
                        .getTargetClass(this.mSelectedObject);
            }
            getEventHandler().sendAction(menuItemSpec.getActionType());
            return true;
        }
        return false;
    }

    @Override
    public boolean onNavigationItemSelected(final int itemPosition,
            final long itemId) {
        if (this.mActionBarSelectionListener != null) {
            String value = null;
            if (this.mIgnoreSelectionIndex != itemPosition) {
                value = this.mActionbarSelectionAdapter.getValue(itemPosition);
            }
            return this.mActionBarSelectionListener.onSelectionItemSelected(
                    itemPosition, value);

        }
        return false;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        final ActionBarSpec menuSpec = getFormDesign().getActionBar();
        final MenuItemSpec itemSpec = menuSpec.getOptionMenuItems().get(
                item.getItemId());
        if (item.getItemId() == android.R.id.home) {
            if (menuSpec.isDisplayHomeAsUp()) {
                finishActivity();
            }
        } else {
            if (getFormDesign().hasOptionMenu()) {
                onSubmit(itemSpec);
            }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onPause() {
        super.onPause();

    }

    protected void onPrepareFragment() {

    }

    @Override
    public void onPrepareOptionsMenu(final Menu menu) {
        final ActionBarSpec menuSpec = getFormDesign().getActionBar();
        if (menuSpec != null) {
            menu.clear();
            if (menuSpec.getSearchViewSpec() != null) {
                this.mSearchViewSpec = menuSpec.getSearchViewSpec();
                menu.add(Menu.NONE, this.mSearchViewSpec.getID().hashCode(),
                        Menu.NONE, this.mSearchViewSpec.getTitle());
                menu.getItem(0).setShowAsAction(
                        MenuItem.SHOW_AS_ACTION_ALWAYS
                                | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
                final SearchView searchView = new SearchView(
                        getApplicationContext());
                final SearchManager searchManager = (SearchManager) getActivity()
                        .getSystemService(Context.SEARCH_SERVICE);
                final SearchableInfo searchableInfo = searchManager
                        .getSearchableInfo(getActivity().getComponentName());
                searchView.setSearchableInfo(searchableInfo);
                searchView.setQueryHint(mSearchViewSpec.getTitle());
                searchView.setOnCloseListener(new OnCloseListener() {

                    @Override
                    public boolean onClose() {
                        if (mOnSearchListener != null) {
                            mOnSearchListener.onSearchClose();
                        }
                        return false;
                    }
                });
                menu.getItem(0).setActionView(searchView);
            }
            for (int i = 0; i < menuSpec.getOptionMenuItems().size(); i++) {
                final MenuItemSpec menuItemSpec = menuSpec.getOptionMenuItems()
                        .valueAt(i);
                menu.add(Menu.NONE, menuItemSpec.getIDValue(),
                        menuItemSpec.getOrderInCategory(),
                        menuItemSpec.getTitle());
                menu.getItem(i).setIcon(menuItemSpec.getIconID());
                if (menuItemSpec.getShowAsActionType() != null) {
                    menu.getItem(i).setShowAsAction(
                            menuItemSpec.getShowAsActionType().getValue());
                }
            }
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        handleActionBarSelection();
        for (final ApLinkBaseView baseView : this.mListRefreshView) {
            baseView.notifyDataSetChanged();
        }
    }

    private void onSubmit(final ControlSpec controlSpec) {
        this.mSelectedControlSpec = controlSpec;
        if (hasRegisterAlertDialog(controlSpec.getActionType(),
                DialogStatus.CONFIRM)) {
            getAlertDialog().show(controlSpec.getActionType(),
                    DialogStatus.CONFIRM);
        } else {
            submit();
        }
    }

    public void setActionBarSelectionListener(
            final OnActionBarSelectionListener actionBarSelectionListener) {
        this.mActionBarSelectionListener = actionBarSelectionListener;
    }

    protected StartActivityListener setActivityListener(
            final Class<?> startActivity) {
        final StartActivityListener activityListener = new StartActivityListener() {

            @Override
            public void startActivity() {
                GenericFragment.this.startActivity(startActivity,
                        GenericFragment.this.mPassingValue);
            }
        };
        return activityListener;
    }

    public void setActivityResultListener(
            final OnActivityResultListener activityResultListener) {
        this.mActivityResultHandler = activityResultListener;
    }

    public void setAlowRefresh(final boolean isAlowRefresh) {
        this.isAlowRefresh = isAlowRefresh;
    }

    public void setImageFetcher(final ImageFetcher imageFetcher) {
        this.mImageFetcher = imageFetcher;
    }

    public void setOnActionbarButtonClickListener(
            final OnClickListener onActionbarButtonClickListener) {
        this.onActionbarButtonClickListener = onActionbarButtonClickListener;
    }

    public void setOnSearchListener(final OnSearchListener onSearchListener) {
        this.mOnSearchListener = onSearchListener;
    }

    public void setPassedGenericObject(final GenericObject passedGenericObject) {
        this.mPassedGenericObject = passedGenericObject;
    }

    public void setSelectedObject(final GenericObject selectedObject) {
        this.mSelectedObject = selectedObject;
    }

    public void setTargetClass(final Target targetClass) {
        this.mTargetClass = targetClass;
    }

    public void setViewByID(final String id, final ApLinkBaseView baseView) {
        this.mBaseViewByID.put(id, baseView);
    }

    public void showInvalidValidationDialog(final ActionType actionType,
            final ValidationResult result) {
        if (!TextUtils.isEmpty(result.getMessage())) {
            if (getAlertDialog().has(actionType,
                    DialogStatus.INVALID_VALIDATION)) {
                getAlertDialog().show(mSelectedControlSpec.getActionType(),
                        DialogStatus.INVALID_VALIDATION, result.getMessage());
            }
        }
    }

    public void startActivity(final Class<?> target,
            final PassingValue passingValue) {
        if (target == null) {
            return;
        }
        final Intent intent = new Intent(getApplicationContext(), target);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (!passingValue.isEmpty()) {
            final Bundle bundle = new Bundle();
            GenericObject mainRecord = null;
            if (this.mContentData == null) {
                mainRecord = this.mInitValues;
            } else {
                mainRecord = this.mSelectedObject;
            }
            final GenericObject genericObject = new GenericObject();
            for (final Column column : passingValue) {
                if (TextUtils.isEmpty(column.getDefaultValue())) {
                    genericObject.put(column.getColumnName(),
                            mainRecord.get(column.getColumnName()));
                } else {
                    genericObject.put(column.getColumnName(),
                            column.getDefaultValue());
                }
            }

            bundle.putSparseParcelableArray(BundleConstant.SELECTED_OBJECT,
                    genericObject);
            intent.putExtras(bundle);
        }
        getActivity().startActivity(intent);
        getActivity().overridePendingTransition(
                getFormDesign().getAnimationInID(),
                getFormDesign().getAnimationOutID());
    }

    public void startActivity(final Class<?> target,
            final PassingValue passingValue, final GenericObject mainRecord) {
        if (target == null) {
            return;
        }
        final Intent intent = new Intent(getApplicationContext(), target);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (!passingValue.isEmpty()) {
            final Bundle bundle = new Bundle();
            final GenericObject genericObject = new GenericObject();
            for (final Column column : passingValue) {
                if (TextUtils.isEmpty(column.getDefaultValue())) {
                    genericObject.put(column.getColumnName(),
                            mainRecord.get(column.getColumnName()));
                } else {
                    genericObject.put(column.getColumnName(),
                            column.getDefaultValue());
                }
            }

            bundle.putSparseParcelableArray(BundleConstant.SELECTED_OBJECT,
                    genericObject);
            intent.putExtras(bundle);
        }
        getActivity().startActivity(intent);
        getActivity().overridePendingTransition(
                getFormDesign().getAnimationInID(),
                getFormDesign().getAnimationOutID());
    }

    public void submit() {
        if (mSelectedControlSpec != null) {
            if (hasRegisterProgressDialog(mSelectedControlSpec.getActionType())) {
                getProgressDialog(mSelectedControlSpec.getActionType()).show();
            }
            new ControlValidationTask(this).executeOnExecutor(
                    AsyncTask.THREAD_POOL_EXECUTOR, mSelectedControlSpec);
        }
    }
}
